package web_util

import (
	web_constants "app/app_src/framework/constant/web"
	"app/app_src/framework/i18n"
	template_funcs "app/app_src/framework/template/funcs"
	template_wrapper "app/app_src/framework/template/wrapper"
	"bytes"
	"fmt"
	"html/template"
	"io"
	"net/http"
	"strings"
	"sync"

	source_code_util "app/app_src/framework/template/util/source_code"

	"github.com/gin-gonic/gin"
)

// 缓存
var _ScriptCache sync.Map

func _InitScriptUtil(utilContext *UtilContext) {
	config := utilContext.ScriptTemplateConfig

	if config != nil {
		funcMap := template.FuncMap{
			"t":           template_funcs.NewScriptI18nFunc(),
			"currentLang": template_funcs.NewCurrentLangFunc(),
		}

		var parser = template_wrapper.NewTemplateParser(template_wrapper.TEMPLATE_TYPE_TEXT, funcMap)
		parser.LeftDelim = config.LeftDelim
		parser.RightDelim = config.RightDelim

		var loader = template_wrapper.NewTemplateLoader(config.PathPrefix, config.PathSuffix, parser)
		loader.CacheEnabled = config.CacheEnabled
		loader.UseEmbedFS = config.UseEmbedFS
		loader.OnReadFile = _ReadScript

		utilContext._ScriptTemplateLoader = loader
	} else {
		panic("UtilContext.ScriptTemplateConfig nil")
	}
}

// 渲染脚本
func RenderScript(ctx *gin.Context, name string) {
	ctx.Status(http.StatusOK)
	ctx.Header(web_constants.HEADER_CONTENT_TYPE, web_constants.RESPONSE_HEADER_CONTENT_TYPE_SCRIPT)

	writer := ctx.Writer
	suffix := _UtilContext.ScriptTemplateConfig.PathSuffix
	name = strings.TrimSuffix(name, suffix)
	_DoWriteScript(writer, name)
	writer.Flush()
}

func _DoWriteScript(writer io.Writer, name string) {
	if _UtilContext.ScriptCacheEnabled {
		var content string
		cacheKey := fmt.Sprint(i18n.GetLangCode(), ":", name)

		// 从缓存中获取
		value, ok := _ScriptCache.Load(cacheKey)
		if ok {
			content = value.(string)
		} else {
			var buffer bytes.Buffer
			tmpl := _UtilContext._ScriptTemplateLoader.LoadTemplate(name)
			// 渲染模板
			err := tmpl.RenderTemplate(&buffer, nil)

			if err != nil {
				panic(err)
			}

			content = buffer.String()
		}

		// 缓存渲染后的 js 内容
		_ScriptCache.Store(cacheKey, content)
		// 返回 js 内容给客户端
		writer.Write([]byte(content))
	} else {
		tmpl := _UtilContext._ScriptTemplateLoader.LoadTemplate(name)
		// 渲染模板并返回给客户端
		err := tmpl.RenderTemplate(writer, nil)

		if err != nil {
			panic(err)
		}
	}
}

func _ReadScript(loader *template_wrapper.TemplateLoader, name string) string {
	content := loader.ReadFile(name)
	sourceCode := source_code_util.GetSourceCode([]byte(content))

	return string(sourceCode)
}
